﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;

using PetriNetSharp.Engine;
using PetriNetSharp.Converter;

namespace PetriNetSharp.View
{
	/// <summary>
	/// Interaction logic for PlaceView.xaml
	/// </summary>
	public partial class PlaceView : UserControl
	{

		/// <summary>
		/// Identifies the Token dependency property
		/// </summary>
		public static readonly DependencyProperty TokenProperty =
			DependencyProperty.Register("Token", typeof(int), typeof(PlaceView),
			new PropertyMetadata(0));

		/// <summary>
		/// Identifies the Max Token dependency property
		/// </summary>
		public static readonly DependencyProperty MaxTokenProperty =
			DependencyProperty.Register("MaxToken", typeof(int), typeof(PlaceView),
			new PropertyMetadata(100));

		/// <summary>
		/// Identifies the Place Name dependency property
		/// </summary>
		public static readonly DependencyProperty PlaceNameProperty =
			DependencyProperty.Register("PlaceName", typeof(string), typeof(PlaceView), 
			new PropertyMetadata(""));

		/// <summary>
		/// Identifies the TokenIsEnabled Property
		/// </summary>
		public static readonly DependencyProperty TokenIsEnabledProperty =
			DependencyProperty.Register("TokenIsEnabled", typeof(bool), typeof(PlaceView), 
			new PropertyMetadata(true));
		

		/// <summary>
		/// Identifies the PlaceNameIsEnabled Property
		/// </summary>
		public static readonly DependencyProperty PlaceNameIsEnabledProperty =
			DependencyProperty.Register("PlaceNameIsEnabledProperty", typeof(bool), 
			typeof(PlaceView), new PropertyMetadata(false));


		/// <summary>
		/// Create a new PlaceView with default values
		/// </summary>
		public PlaceView()
		{
			
			InitializeComponent();

			//Bind the slider and text box to the token, max token,
			//and name dependency properties
			Binding bind = new Binding();
			bind.Source = this;
			bind.Path = new PropertyPath(TokenProperty);
			bind.Mode = BindingMode.TwoWay;
			tokenSlider.SetBinding(Slider.ValueProperty, bind);

			bind = new Binding();
			bind.Source = this;
			bind.Path = new PropertyPath(MaxTokenProperty);
			bind.Mode = BindingMode.TwoWay;
			tokenSlider.SetBinding(Slider.MaximumProperty, bind);


			bind = new Binding();
			bind.Source = this;
			bind.Path = new PropertyPath(PlaceNameProperty);
			bind.Mode = BindingMode.TwoWay;
			bind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
			nameTextBox.SetBinding(TextBox.TextProperty, bind);

			//Bind the slider and text box is enables to TokenIsEnabled and 
			//NameIsEnabled dependency properties
			bind = new Binding();
			bind.Source = this;
			bind.Path = new PropertyPath(TokenIsEnabledProperty);
			bind.Mode = BindingMode.TwoWay;
			tokenSlider.SetBinding(Slider.IsEnabledProperty, bind);

			bind = new Binding();
			bind.Source = this;
			bind.Path = new PropertyPath(PlaceNameIsEnabledProperty);
			bind.Mode = BindingMode.TwoWay;
			nameTextBox.SetBinding(TextBox.IsEnabledProperty, bind);
		}

		/// <summary>
		/// Get or set the place name
		/// </summary>
		public string PlaceName
		{
			get { return (string)GetValue(PlaceNameProperty); }
			set { SetValue(PlaceNameProperty, value); }
		}

		/// <summary>
		/// Get or set the tokens
		/// </summary>
		public int Tokens
		{
			get { return (int)GetValue(TokenProperty); }
			set { SetValue(TokenProperty, value); }
		}

		/// <summary>
		/// Get or set the Max Tokens
		/// </summary>
		public int MaxTokens
		{
			get { return (int)GetValue(MaxTokenProperty); }
			set { SetValue(MaxTokenProperty, value); }
		}

		/// <summary>
		/// Get or set whether the token visual is enabled
		/// </summary>
		/// <remarks>
		/// Can the user interact with the token visual or not
		/// </remarks>
		public bool TokenIsEnabled
		{
			get { return (bool)GetValue(TokenIsEnabledProperty); }
			set { SetValue(TokenIsEnabledProperty, value); }
		}

		/// <summary>
		/// Get or set whether the name visual is enabled
		/// </summary>
		/// <remarks>
		/// Can the user interact with the name visual or not
		/// </remarks>
		public bool PlaceNameIsEnabled
		{
			get { return (bool)GetValue(PlaceNameIsEnabledProperty); }
			set { SetValue(PlaceNameIsEnabledProperty, value); }
		}

		#region focus functionality

		/// <summary>
		/// On the mouse down for the ellipse the focus is set
		/// </summary>
		/// <param name="sender">Not used at this time</param>
		/// <param name="e">Not used at this time</param>
		private void ellipse_MouseDown(object sender, MouseButtonEventArgs e)
		{
			FocusManager.SetFocusedElement(Parent, this);
		}

		/// <summary>
		/// When the control gets focus performs the visual changes
		/// </summary>
		/// <param name="sender">Not used at this time</param>
		/// <param name="e">Not used at this time</param>
		private void UserControl_GotFocus(object sender, RoutedEventArgs e)
		{
			ellipse.SetResourceReference(Ellipse.StrokeThicknessProperty, 
				"SelectedBorderThickness");
		}

		/// <summary>
		/// When the control loses focus performs the visual changes
		/// </summary>
		/// <param name="sender">Not used at this time</param>
		/// <param name="e">Not used at this time</param>
		private void UserControl_LostFocus(object sender, RoutedEventArgs e)
		{
			ellipse.SetResourceReference(Ellipse.StrokeThicknessProperty, 
				"DeselectedBorderThickness");
		}

		/// <summary>
		/// When the text box gets keyboard focus sets logical focus as well
		/// </summary>
		/// <param name="sender">Not used at this time</param>
		/// <param name="e">Not used at this time</param>
		private void nameTextBox_GotKeyboardFocus(object sender, 
			KeyboardFocusChangedEventArgs e)
		{
			FocusManager.SetFocusedElement(Parent, this);
		}

		/// <summary>
		/// When the slider gets keyboard focus sets logical focus as well
		/// </summary>
		/// <param name="sender">Not used at this time</param>
		/// <param name="e">Not used at this time</param>
		private void tokenSlider_GotKeyboardFocus(object sender, 
			KeyboardFocusChangedEventArgs e)
		{
			FocusManager.SetFocusedElement(Parent, this);
		}

		#endregion

		#region static methods

		/// <summary>
		/// Get the Height of a PlaceView
		/// </summary>
		/// <remarks>
		/// Right now this is kind of a hack, I should see if there is a 
		/// better way to look this up
		/// </remarks>
		public static double PlaceHeight
		{
			get
			{
				FrameworkElement e = new FrameworkElement();
				return (double)e.FindResource("PlaceHeight");
			}
		}

		/// <summary>
		/// Get the Width of a PlaceView
		/// </summary>
		/// <remarks>
		/// Right now this is kind of a hack, I should see if there is a 
		/// better way to look this up
		/// </remarks>
		public static double PlaceWidth
		{
			get
			{
				FrameworkElement e = new FrameworkElement();
				return (double)e.FindResource("PlaceWidth");
			}
		}

		#endregion
	}
}
